package com.xtoneict.auth.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xtoneict.auth.entity.*;
import com.xtoneict.auth.entity.param.*;
import com.xtoneict.auth.service.*;
import com.xtoneict.auth.service.impl.WorkTimeFileServiceImpl;
import com.xtoneict.auth.vo.FileVO;
import com.xtoneict.auth.vo.UserVO;
import com.xtoneict.util.result.Result;
import com.xtoneict.util.utils.AuditConstant;
import com.xtoneict.util.utils.DateUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/auth/file")
public class FileController {
    @Autowired
    private IWorkTimeFileService workTimeFileService;
    @Autowired
    private IDepartmentService departmentService;
    @Autowired
    private IDayDetailService dayDetailService;
    @Autowired
    private IWorkProjectService workProjectService;
    @Autowired
    private IEmployeeService employeeService;
    @Autowired
    private IAttendanceService attendanceService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private ILeaveDayService leaveDayService;
    @Autowired
    private IYearMonthTabService yearMonthTabService;
    @Autowired
    private IUserService userService;
    @Autowired
    private HolidayController holidayController;

    /**
     * 新增工时表
     * @param workTimeFile
     * @return
     */
    @RequestMapping("/insert")
    public Result insert(@RequestBody WorkTimeFile workTimeFile){
        workTimeFileService.Insert(workTimeFile);

        return Result.ok();
    }

    /**
     * 删除工时表
     * 注意：逻辑删除
     * @param ids
     * @return
     */
    @RequestMapping("remove")
    public Result remove(@RequestBody List<Integer> ids) {
        for(Integer id : ids) {
            //删除user_file表中相关数据
            List<Integer> userIds = workTimeFileService.selectUserIdByFile(id);
            List<Integer> fileIds = new ArrayList<>();
            fileIds.add(id);
            workTimeFileService.deleteUserAndFile(userIds,fileIds);
        }

        //逻辑删除file
        for(Integer id : ids) {
            boolean is_success = workTimeFileService.removeById(id);
        }

        return Result.ok();
    }

    /**
     * 分页查询
     * @return
     */
    @RequestMapping("page")
    public Result page(@RequestBody FilePageParam filePageParam){
        HashMap<String, Object> map = new HashMap<>();
        List<FileVO> fileVOS = new ArrayList<>();

        if(filePageParam.getManager() == null){
            FilePageResultParam filePageResultParam = (FilePageResultParam) workTimeFileService.selectFiles(filePageParam);
            List<WorkTimeFile> files = filePageResultParam.getWorkTimeFiles();
            Integer total = filePageResultParam.getTotal();
            for (WorkTimeFile file : files){
                FileVO fileVO = new FileVO();
                BeanUtils.copyProperties(file, fileVO);

                List<Integer> userIds = workTimeFileService.selectUserIdByFile(fileVO.getFileId());
                List<User> users = userService.listByIds(userIds);
                fileVO.setUsers(users);

                fileVOS.add(fileVO);
            }

            map.put("files", fileVOS);
            map.put("total", total);

            return Result.ok(map);
        }else {
            List<WorkTimeFile> fileList = workTimeFileService.selectFilesForManager(filePageParam);
            List<WorkTimeFile> files1 = new ArrayList<>();

            //获取该审核人员才能看的文件id
            List<Integer> fileIds = workTimeFileService.selectFileIdsByUser(filePageParam.getManager());

            for (WorkTimeFile file : fileList){
                if(fileIds.contains(file.getFileId())){
                    files1.add(file);
                }
            }
            for (WorkTimeFile file : files1){
                FileVO fileVO = new FileVO();
                BeanUtils.copyProperties(file, fileVO);

                List<Integer> userIds = workTimeFileService.selectUserIdByFile(fileVO.getFileId());
                List<User> users = userService.listByIds(userIds);
                fileVO.setUsers(users);

                fileVOS.add(fileVO);
            }

            map.put("files", fileVOS);
            map.put("total", fileVOS.size());

            return Result.ok(map);
        }
    }

    /**
     * 用于分发工时表
     * 插入userAndFile数据即可
     * @param listParam
     * @return
     */
    @RequestMapping("/insertUserAndFile")
    public Result insertUserAndFile(@RequestBody ListParam listParam){
        List<Integer> userIds = listParam.getUserIds();
        List<Integer> fileIds = listParam.getFileIds();
        workTimeFileService.InsertUserAndFileBatch(userIds, fileIds);

        return Result.ok();
    }

    /**
     * 删除用户对工时表查看权限
     * @param listParam
     * @return
     */
    @RequestMapping("/deleteUserAndFile")
    public Result deleteUserAndFile(@RequestBody ListParam listParam){
        List<Integer> userIds = listParam.getUserIds();
        List<Integer> fileIds = listParam.getFileIds();

        workTimeFileService.deleteUserAndFile(userIds, fileIds);

        return Result.ok();
    }

    @RequestMapping("/generate")
    public Result generateFile(@RequestBody YearMonthParam yearMonthParam) throws IOException {
        if(yearMonthParam.getYear() == null){
            System.out.println("year为空");
        }
        if(yearMonthParam.getMonth() == null){
            System.out.println("month为空");
        }
        Integer year = yearMonthParam.getYear();
        Integer month = yearMonthParam.getMonth();
        //取出yearMonthId，方便后续使用
        YearMonthTab yearMonthTab = yearMonthTabService.getByYearAndMonth(year, month);
        Integer yearMonthId = yearMonthTab.getYearMonthId();

        //得到相关的attendance
        QueryWrapper<Attendance> attendanceQueryWrapper = new QueryWrapper<>();
        attendanceQueryWrapper.eq("year_month_id", yearMonthId);
        List<Attendance> attendances = attendanceService.list(attendanceQueryWrapper);

        for (Attendance attendance : attendances){
            //获取基本信息
            Integer emloyeeId = attendance.getEmployeeId();
            Integer depId = employeeService.getById(emloyeeId).getDepId();
            String employeeName = employeeService.getById(emloyeeId).getName();
            //未出勤天数
            double leaveCount = attendanceService.leaveDayCount(attendance.getAttendanceId());

            //填写工时统计表基本信息
            WorkTimeFile workTimeFile = new WorkTimeFile();
            workTimeFile.setDepId(depId);
            workTimeFile.setDepName(departmentService.getById(depId).getDepName());
            workTimeFile.setEmployeeId(emloyeeId);
            workTimeFile.setEmployeeName(employeeName);
            workTimeFile.setLeaveCount(leaveCount);
            workTimeFile.setYearMonthId(yearMonthId);
            workTimeFile.setYear(year);
            workTimeFile.setMonth(month);
            //自己拼接生成filename
            //生成filename: “2024年5月经营管理部张三工时统计表”
            workTimeFile.setFileName(year + "年" + month + "月" + departmentService.getById(depId).getDepName() + employeeName + "工时统计表");

            workTimeFileService.save(workTimeFile);

            /**
             * 生成之后，自动添加管理员可见
             */
            List<Integer> userIds = new ArrayList<>();
            userIds.add(21);
            List<Integer> fileIds = new ArrayList<>();
            //添加成功之后，那么原有对象就会带有ID值，就可以点出来
            fileIds.add(workTimeFile.getFileId());

            workTimeFileService.InsertUserAndFileBatch(userIds, fileIds);

            //从attendance得出里面这个月工作总天数
            int dayCount = attendance.getWorkDays();
            //得出出勤总天数
            double workCount = dayCount - leaveCount;

            //根据employeeId和年月得出project
            /*改*/
            QueryWrapper<Project> projectsWrapper = new QueryWrapper<>();
            projectsWrapper.eq("employee_id", emloyeeId);
            projectsWrapper.eq("year_month_id", yearMonthId);
            List<Project> projects = projectService.list(projectsWrapper);

            for (Project project : projects){
                //获取项目总工时
                double workTime = project.getProjectTime();
                //获取每一天平均工时
                double averageTime = workTime / workCount;

                WorkProject workProject = new WorkProject();
                workProject.setEmployeeId(emloyeeId);
                workProject.setProjectId(project.getProjectId());
                workProject.setWorkProjectCode(project.getProjectCode());
                workProject.setWorkProjectName(project.getProjectName());
                workProject.setWorkProjectTime(project.getProjectTime());
                workProject.setWorkTimeFileId(workTimeFile.getFileId());

                workProjectService.save(workProject);

                //获取这个月总天数
                DateUtil dateUtil = new DateUtil();
                int dayTotal = dateUtil.getMonthCount(year, month);

                for (int i = 1;i <= dayTotal;i++){
                    DayDetail dayDetail = new DayDetail();
                    dayDetail.setDay(i);
                    dayDetail.setWorkProjectId(workProject.getWorkProjectId());
                    dayDetail.setEmployeeId(emloyeeId);
                    dayDetail.setYearMonthId(yearMonthId);

                    //记录工时
                    char res = holidayController.judgeIfHoliday(year, month, i);

                    //是否是工作日
                    if(res == '0'){
                        dayDetail.setType("工作日");
                        //进行是否请假判断
                        LeaveDay leaveDay = leaveDayService.selectLeaveDay(attendance.getEmployeeId(), yearMonthId, i);
                        if(leaveDay != null){
                            if (leaveDay.isHalfDay()){
                                //请了半天假，按照半天的工作日处理

                                dayDetail.setWorkTime(averageTime/2);
                                //计算这一天已经填入的总工时
//                                double alreadyTotalWorkTime = dayDetailService.countToTalWorkTimeOneDay(emloyeeId, yearMonthId, i);

//                                if(alreadyTotalWorkTime < 3.5){
//                                    if((alreadyTotalWorkTime + averageTime) <= 3.5){
//                                        dayDetail.setWorkTime(averageTime);
//                                    }else {
//                                        dayDetail.setWorkTime(3.5 - alreadyTotalWorkTime);
//                                    }
//                                }else {
//                                    dayDetail.setWorkTime(0);
//                                }
                            }else {
                                //请了整天假，工时直接为0
                                dayDetail.setWorkTime(0);
                            }
                        }else {
                            //未请假，按照工作日处理

                            //计算这一天已经填入的总工时
//                            double alreadyTotalWorkTime = dayDetailService.countToTalWorkTimeOneDay(emloyeeId, yearMonthId, i);

//                            if(alreadyTotalWorkTime < 7){
//                                //该天工时还未满
//                                if((alreadyTotalWorkTime + averageTime) <= 7){
//                                    //该天已有工时加上平均工时未满，则直接加上平均工时
//                                    dayDetail.setWorkTime(averageTime);
//                                }else {
//                                    //该天已有工时加上平均工时满了，则加上剩下能加的工时
//                                    dayDetail.setWorkTime(7 - alreadyTotalWorkTime);
//                                }
//                            }else {
//                                //这一天的工时已经填满了，所以该项目该天工时为0
//                                dayDetail.setWorkTime(0);
//                            }
                            dayDetail.setWorkTime(averageTime);
                        }

                    }else if(res == '1' || res == '2'){
                        dayDetail.setType("休假");
                        //是休息日或节假日，工时直接为0
                        dayDetail.setWorkTime(0);
                    }


                    //存储到数据库中
                    dayDetailService.save(dayDetail);
                }
            }

        }

        return Result.ok();
    }


    /**
     * 显示工时表详细信息
     * @param fileId
     * @return
     */
    @RequestMapping("/showDetail")
    public Result showDetail(Integer fileId){
        WorkTimeFile workTimeFile = workTimeFileService.getById(fileId);

        QueryWrapper<WorkProject> workProjectQueryWrapper = new QueryWrapper<>();
        /*
        这里的字段名到底是数据库还是对象名？
         */
        workProjectQueryWrapper.eq("work_time_file_id", fileId);
        List<WorkProject> workProjects = workProjectService.list(workProjectQueryWrapper);

        for (WorkProject workProject : workProjects){
            QueryWrapper<DayDetail> dayDetailQueryWrapper = new QueryWrapper<>();
            dayDetailQueryWrapper.eq("work_project_id",workProject.getWorkProjectId());
            List<DayDetail> dayDetails = dayDetailService.list(dayDetailQueryWrapper);

            workProject.setDayDetails(dayDetails);
        }

        workTimeFile.setWorkProjects(workProjects);

        return Result.ok(workTimeFile);
    }

    @RequestMapping("/audit")
    public Result changeAudit(@RequestBody AuditParam auditParam){
        Integer fileId = auditParam.getFileId();
        Integer ifPass = auditParam.getIfPass();

        UpdateWrapper<WorkTimeFile> workTimeFileUpdateWrapper = new UpdateWrapper<>();

        if(ifPass == 1){
            workTimeFileUpdateWrapper.eq("file_id", fileId).set("pass_status", AuditConstant.PASS);
        }else {
            workTimeFileUpdateWrapper.eq("file_id", fileId).set("pass_status", AuditConstant.NO_PASS);

            if(auditParam.getNoPassReason() != null){
                workTimeFileUpdateWrapper.eq("file_id", fileId).set("no_pass_reason", auditParam.getNoPassReason());
            }
        }

        workTimeFileService.update(workTimeFileUpdateWrapper);

        return Result.ok();
    }

}
